package com.yanqu.road.server.manager.marriage;

import com.yanqu.road.entity.enums.eMarriageStatusType;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.entity.servercenter.group.CrossMarriageGroup;
import com.yanqu.road.logic.bussiness.marriage.CrossMarriageBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.MarriagePb;
import com.yanqu.road.pb.common.CommonProto;
import com.yanqu.road.pb.marriage.CrossMarriageProto;
import com.yanqu.road.pb.marriage.MarriageProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.banquet.CrossPartyMgr;
import com.yanqu.road.server.manger.CrossMarriageGroupMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 玩家跨服联姻管理类
 */
public class CrossGroupMarriageMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(CrossGroupMarriageMgr.class.getName());

    private static RandomHelper randomHelper = new RandomHelper();
    /**
     * 子嗣编号，子嗣数据
     */
    private static Map<String, MarriageInfo> allMarriageMap = new ConcurrentHashMap<>();
    /**
     * 分组，子嗣编号，子嗣数据
     */
    private static Map<Integer, Map<String, MarriageInfo>> serverApplyMap = new ConcurrentHashMap<>();
    /**
     * 分组，服务器，玩家，子嗣编号，子嗣数据
     */
    private static Map<Integer, Map<Long, Map<Long, Map<String, MarriageInfo>>>> appointApplyMap = new ConcurrentHashMap<>();
    /**
     * 服务器，玩家，性别，子嗣编号，子嗣数据
     */
    private static Map<Long, Map<Long, Map<Integer, Map<String, MarriageInfo>>>> allServerApplyMap = new ConcurrentHashMap<>();

    private static Object locker = new Object();

    @Override
    public boolean init() throws Exception {
        addMarriageGroupReloadListener();
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean reloadData() {
        synchronized (locker) {
            allMarriageMap = CrossMarriageBusiness.getMarriageInfoMap();
            initMarriageApply();
        }
        return true;
    }

    @Override
    public boolean save() {
        List<String> needRemoveList = new ArrayList<>();
        for(MarriageInfo marriageInfo : allMarriageMap.values()){
            if(marriageInfo.isInsertOption()){
                CrossMarriageBusiness.addMarriageInfo(marriageInfo);
            }else if(marriageInfo.isUpdateOption()){
                CrossMarriageBusiness.updateMarriageInfo(marriageInfo);
            }
            if (marriageInfo.getStatus() == eMarriageStatusType.MARRIED && !marriageInfo.isDirty()) {
                needRemoveList.add(marriageInfo.getChildUid());
            }
        }
        for (String childUid : needRemoveList) {
            allMarriageMap.remove(childUid);
        }
        return true;
    }

    private void addMarriageGroupReloadListener() {
        CrossMarriageGroupMgr.addReloadListener(() -> {
            groupChange();
            // 先结算宴会
            CrossPartyMgr.changeGroup();
            notifyServerReload();
            logger.info("marriage group reload");
        });
    }

    private static void initMarriageApply() {
        synchronized (locker) {
            serverApplyMap = new ConcurrentHashMap<>();
            appointApplyMap = new ConcurrentHashMap<>();
            for (MarriageInfo data : allMarriageMap.values()) {
                if (data.getStatus() == eMarriageStatusType.CrossPublish) {//如果是发布联姻状态
                    if (isOverApplyTime(data)) {
                        data.setStatus(eMarriageStatusType.WAIT);
                    } else {

                        if (data.getAppointUserId() > 0) {//指定联姻
                            CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(data.getPartnerServerId());
                            if (CrossMarriageGroupMgr.canCrossMarriage(marriageGroup) && CrossMarriageGroupMgr.canCrossMarriage(data.getServerId())) {
                                if (!appointApplyMap.containsKey(marriageGroup.getGroupId())) {
                                    appointApplyMap.put(marriageGroup.getGroupId(), new ConcurrentHashMap<>());
                                }
                                Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointMap = appointApplyMap.get(marriageGroup.getGroupId());
                                if (!groupAppointMap.containsKey(data.getPartnerServerId())) {
                                    groupAppointMap.put(data.getPartnerServerId(), new ConcurrentHashMap<>());
                                }
                                Map<Long, Map<String, MarriageInfo>> serverAppointMap = groupAppointMap.get(data.getPartnerServerId());
                                if (!serverAppointMap.containsKey(data.getAppointUserId())) {
                                    serverAppointMap.put(data.getAppointUserId(), new ConcurrentHashMap<>());
                                }
                                serverAppointMap.get(data.getAppointUserId()).put(data.getChildUid(), data);
                            }
                        } else {
                            CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(data.getServerId());
                            if (CrossMarriageGroupMgr.canCrossMarriage(marriageGroup)) {
                                if (!serverApplyMap.containsKey(marriageGroup.getGroupId())) {
                                    serverApplyMap.put(marriageGroup.getGroupId(), new ConcurrentHashMap<>());
                                }
                                serverApplyMap.get(marriageGroup.getGroupId()).put(data.getChildUid(), data);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 发布指向联姻
     *
     * @param serverId
     * @param marriageInfo
     * @param appointUserId
     * @param partnerServerId
     * @return
     */
    public static int publishAppointMarriage(long serverId, MarriageInfo marriageInfo, long appointUserId, long partnerServerId, BigInteger limitEarnSpeed) {
        if (serverId == partnerServerId) {
            return GameErrorCode.E_CROSS_MARRIAGE_SERVER_NO_SAME;
        }
        CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(serverId);
        if (!CrossMarriageGroupMgr.canCrossMarriage(marriageGroup)) {
            return GameErrorCode.E_CROSS_MARRIAGE_NO_OPEN;
        }
        if (!marriageGroup.getServerList().contains(partnerServerId)) {
            return GameErrorCode.E_CROSS_MARRIAGE_PARTNER_NO_IN_GROUP;
        }
        if (getAppointApply(marriageGroup.getGroupId(), partnerServerId, appointUserId).size() >= GameConfig.CROSS_MARRIAGE_MAX_APPOINT_APPLY_COUNT) {
            return GameErrorCode.E_MARRIAGE_APPOINT_APPLY_MAX;
        }
        //通知对方联姻请求
        CrossMarriageProto.CrossMarriageAppointReqMsg.Builder notifyMsg = CrossMarriageProto.CrossMarriageAppointReqMsg.newBuilder();
        notifyMsg.setApplyData(MarriagePb.parseMarriageApplyTempMsg(marriageInfo));
        notifyMsg.setLimitEarnSpeed(limitEarnSpeed.toString());
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_MARRIAGE_APPOINT_REQ, notifyMsg);
        MessageHelper.sendPacket(partnerServerId, appointUserId, pbMsg);
        return 0;
    }

    /**
     * 跨服指向联姻响应处理
     *
     * @param result
     * @param marriageInfo
     * @param appointUserId
     * @param partnerServerId
     * @return
     */
    public static int publishAppointMarriageResponse(int result, MarriageInfo marriageInfo, long appointUserId, long partnerServerId) {
        if (0 != result) {
            return result;
        }
        CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(marriageInfo.getServerId());
        if (!CrossMarriageGroupMgr.canCrossMarriage(marriageGroup)) {
            return GameErrorCode.E_CROSS_MARRIAGE_NO_OPEN;
        }
        if (!marriageGroup.getServerList().contains(partnerServerId)) {
            return GameErrorCode.E_CROSS_MARRIAGE_PARTNER_NO_IN_GROUP;
        }
        if (!appointApplyMap.containsKey(marriageGroup.getGroupId())) {
            synchronized (appointApplyMap) {
                if (!appointApplyMap.containsKey(marriageGroup.getGroupId())) {
                    appointApplyMap.put(marriageGroup.getGroupId(), new ConcurrentHashMap<>());
                }
            }
        }
        Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointApplyMap = appointApplyMap.get(marriageGroup.getGroupId());
        if (!groupAppointApplyMap.containsKey(partnerServerId)) {
            synchronized (groupAppointApplyMap) {
                if (!groupAppointApplyMap.containsKey(partnerServerId)) {
                    groupAppointApplyMap.put(partnerServerId, new ConcurrentHashMap<>());
                }
            }
        }
        Map<Long, Map<String, MarriageInfo>> serverAppointApplyMap = groupAppointApplyMap.get(partnerServerId);
        synchronized (serverAppointApplyMap) {
            if (getAppointApply(marriageGroup.getGroupId(), partnerServerId, appointUserId).size() >= GameConfig.CROSS_MARRIAGE_MAX_APPOINT_APPLY_COUNT) {
                return GameErrorCode.E_MARRIAGE_APPOINT_APPLY_MAX;
            }
            if (!serverAppointApplyMap.containsKey(appointUserId)) {
                serverAppointApplyMap.put(appointUserId, new ConcurrentHashMap<>());
            }
            Map<String, MarriageInfo> userAppointApplyMap = serverAppointApplyMap.get(appointUserId);
            marriageInfo.setAppointUserId(appointUserId);
            marriageInfo.setPartnerServerId(partnerServerId);
            marriageInfo.setStatus(eMarriageStatusType.CrossPublish);
            MarriageInfo tempMarriage = putMarriage(marriageInfo);
            userAppointApplyMap.put(marriageInfo.getChildUid(), tempMarriage);
        }
        //通知对方联姻请求
        MarriageProto.MarriageApplyTempMsg.Builder notifyMsg = MarriagePb.parseMarriageApplyTempMsg(marriageInfo);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_MARRIAGE_APPOINT_NOTIFY, notifyMsg);
        MessageHelper.sendPacket(partnerServerId, appointUserId, pbMsg);
        return 0;
    }

    /**
     * 发布非指向联姻
     *
     * @param serverId
     * @param marriageInfo
     * @return
     */
    public static int publishServerMarriage(long serverId, MarriageInfo marriageInfo) {
        CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(serverId);
        if (!CrossMarriageGroupMgr.canCrossMarriage(marriageGroup)) {
            return GameErrorCode.E_CROSS_MARRIAGE_NO_OPEN;
        }
        if (!serverApplyMap.containsKey(marriageGroup.getGroupId())) {
            synchronized (serverApplyMap) {
                if (!serverApplyMap.containsKey(marriageGroup.getGroupId())) {
                    serverApplyMap.put(marriageGroup.getGroupId(), new ConcurrentHashMap<>());
                }
            }
        }
        Map<String, MarriageInfo> groupApplyMap = serverApplyMap.get(marriageGroup.getGroupId());
        synchronized (groupApplyMap) {
            marriageInfo.setStatus(eMarriageStatusType.CrossPublish);
            MarriageInfo tempMarriage = putMarriage(marriageInfo);
            groupApplyMap.put(marriageInfo.getChildUid(), tempMarriage);
        }
        return 0;
    }

    /**
     * 把联姻放到内存
     *
     * @param marriageInfo
     * @return
     */
    private static MarriageInfo putMarriage(MarriageInfo marriageInfo) {
        MarriageInfo tempMarriage;
        if (!allMarriageMap.containsKey(marriageInfo.getChildUid())) {
            synchronized (allMarriageMap) {
                if (!allMarriageMap.containsKey(marriageInfo.getChildUid())) {
                    marriageInfo.setInsertOption();
                    allMarriageMap.put(marriageInfo.getChildUid(), marriageInfo);
                    tempMarriage = marriageInfo;
                } else {
                    tempMarriage = allMarriageMap.get(marriageInfo.getChildUid());
                    MarriagePb.cloneMarriage(tempMarriage, marriageInfo);
                }
            }
        } else {
            tempMarriage = allMarriageMap.get(marriageInfo.getChildUid());
            MarriagePb.cloneMarriage(tempMarriage, marriageInfo);
        }
        return tempMarriage;
    }

    /**
     * 获取玩家非指向联姻
     */
    public static List<MarriageInfo> getServerApplyList(int groupId, long serverId, long userId, int childSex, BigInteger minEarnSpeed,
                                                        BigInteger maxEarnSpeed) {
        List<MarriageInfo> dataList = new ArrayList<>();
        Map<Long, Map<Integer, Map<String, MarriageInfo>>> userServerApplyMap = allServerApplyMap.get(serverId);
        if (null != userServerApplyMap) {
            if (userServerApplyMap.containsKey(userId)) {
                Map<Integer, Map<String, MarriageInfo>> userApplyMap = userServerApplyMap.get(userId);
                if (userApplyMap.containsKey(childSex)) {
                    Map<String, MarriageInfo> sexApplyMap = userApplyMap.get(childSex);
                    for (MarriageInfo marriageInfo : sexApplyMap.values()) {
                        if (marriageInfo.getStatus() != eMarriageStatusType.CrossPublish || marriageInfo.getServerId() == serverId ||
                                isOverApplyTime(marriageInfo) || !isServerApplyExist(groupId, marriageInfo.getChildUid()) ||
                                marriageInfo.getAppointUserId() > 0
                        ) {//过期或者已联姻的移除掉，变成指定联姻的也要移除掉
                            sexApplyMap.remove(marriageInfo.getChildUid());
                        }
                    }
                    dataList.addAll(sexApplyMap.values());
                }
            }
        }
        if (dataList.size() <= 0) {
            dataList = refreshServerApplyList(groupId, serverId, userId, childSex, minEarnSpeed, maxEarnSpeed);
        }
        return dataList;
    }

    /**
     * 刷新玩家非指向联姻
     */
    public static List<MarriageInfo> refreshServerApplyList(int groupId, long serverId, long userId, int childSex, BigInteger minEarnSpeed,
                                                            BigInteger maxEarnSpeed) {
        List<MarriageInfo> dataList = new ArrayList<>();
        if (!allServerApplyMap.containsKey(serverId)) {
            synchronized (allServerApplyMap) {
                if (!allServerApplyMap.containsKey(serverId)) {
                    allServerApplyMap.put(serverId, new ConcurrentHashMap<>());
                }
            }
        }
        Map<Long, Map<Integer, Map<String, MarriageInfo>>> userServerApplyMap = allServerApplyMap.get(serverId);
        if (!userServerApplyMap.containsKey(userId)) {
            userServerApplyMap.put(userId, new ConcurrentHashMap<>());
        }
        Map<Integer, Map<String, MarriageInfo>> userApplyMap = userServerApplyMap.get(userId);
        if (!userApplyMap.containsKey(childSex)) {
            userApplyMap.put(childSex, new ConcurrentHashMap<>());
        }
        Map<String, MarriageInfo> sexApplyMap = userApplyMap.get(childSex);
        Map<String, MarriageInfo> groupServerApplyMap = serverApplyMap.get(groupId);
        List<MarriageInfo> tempList = new ArrayList<>();
        if (null != groupServerApplyMap) {
            tempList.addAll(groupServerApplyMap.values());
        }
        sexApplyMap.clear();
        if(minEarnSpeed.compareTo(BigInteger.ZERO) > 0 && maxEarnSpeed.compareTo(BigInteger.ZERO) > 0) {
            List<MarriageInfo> sortList = new ArrayList<>();
            for (MarriageInfo marriageInfo : tempList) {
                if (marriageInfo.getStatus() == eMarriageStatusType.MARRIED) {
                    groupServerApplyMap.remove(marriageInfo.getChildUid());
                }
                if (marriageInfo.getChildEarnSpeed().compareTo(minEarnSpeed) >= 0 &&
                        marriageInfo.getChildEarnSpeed().compareTo(maxEarnSpeed) <= 0) {
                    sortList.add(marriageInfo);
                }
            }
            tempList.removeAll(sortList);
            getConditionChildList(serverId, userId, childSex, dataList, sexApplyMap, groupServerApplyMap, sortList);
        }
        if (dataList.size() < GameConfig.MARRIAGE_MAX_SEVER_APPLY_LIST_COUNT) {
            getConditionChildList(serverId, userId, childSex, dataList, sexApplyMap, groupServerApplyMap, tempList);
        }
        return dataList;
    }

    /**
     * 获取符合条件的联姻
     * @param serverId
     * @param userId
     * @param childSex
     * @param resultList
     * @param sexApplyMap
     * @param groupServerApplyMap
     * @param marriageList
     */
    private static void getConditionChildList(long serverId, long userId, int childSex, List<MarriageInfo> resultList,
        Map<String, MarriageInfo> sexApplyMap, Map<String, MarriageInfo> groupServerApplyMap, List<MarriageInfo> marriageList) {
        while (true) {
            if (marriageList.size() > 0) {
                int randomNum = randomHelper.next(0, marriageList.size());
                MarriageInfo marriageInfo = marriageList.get(randomNum);
                if (marriageInfo.getStatus() == eMarriageStatusType.MARRIED) {
                    groupServerApplyMap.remove(marriageInfo.getChildUid());
                }
                if (marriageInfo.getUserId() != userId && marriageInfo.getServerId() != serverId &&
                        marriageInfo.getStatus() == eMarriageStatusType.CrossPublish &&
                        marriageInfo.getChildSex() != childSex && !isOverApplyTime(marriageInfo) &&
                        marriageInfo.getAppointUserId() == 0
                ) {
                    resultList.add(marriageInfo);
                    sexApplyMap.put(marriageInfo.getChildUid(), marriageInfo);
                }
                marriageList.remove(randomNum);
            } else {
                break;
            }
            if (resultList.size() >= GameConfig.MARRIAGE_MAX_SEVER_APPLY_LIST_COUNT) {
                break;
            }
        }
    }

    /**
     * 取消跨服联姻
     *
     * @param groupId
     * @param childUid
     * @return
     */
    public static int cancelMarriage(int groupId, String childUid) {
        MarriageInfo marriageInfo = allMarriageMap.get(childUid);
        if (null == marriageInfo) {
            return GameErrorCode.E_MARRIAGE_CHILD_NO_FOUND;
        }
        if (marriageInfo.getStatus() == eMarriageStatusType.MARRIED) {
            return GameErrorCode.E_MARRIAGE_ALREADY_MARRY;
        }

        if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
            if (marriageInfo.getAppointUserId() != 0 && marriageInfo.getPartnerServerId() != 0) {//指定联姻
                Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointApplyMap = appointApplyMap.get(groupId);
                if (null != groupAppointApplyMap) {
                    Map<Long, Map<String, MarriageInfo>> serverAppointApplyMap = groupAppointApplyMap.get(marriageInfo.getPartnerServerId());
                    if (null != serverAppointApplyMap) {
                        if (serverAppointApplyMap.containsKey(marriageInfo.getAppointUserId())) {
                            serverAppointApplyMap.get(marriageInfo.getAppointUserId()).remove(childUid);
                        }
                    }
                }
                marriageInfo.setAppointUserId(0);
                marriageInfo.setPartnerServerId(0);
            } else {//全服联姻
                Map<String, MarriageInfo> groupServerApplyMap = serverApplyMap.get(groupId);
                if (null != groupServerApplyMap) {
                    groupServerApplyMap.remove(childUid);
                }
            }
            synchronized (locker) {
                if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                    marriageInfo.setStatus(eMarriageStatusType.WAIT);
                }
            }
        }
        return 0;
    }

    /**
     * 拒绝联姻请求
     *
     * @param groupId
     * @param serverId
     * @param userId
     * @param childUid
     * @return
     */
    public static int refuseMarriage(int groupId, long serverId, long userId, String childUid) {
        Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointApplyMap = appointApplyMap.get(groupId);
        if (null == groupAppointApplyMap) {
            return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
        }
        Map<Long, Map<String, MarriageInfo>> serverAppointApplyMap = groupAppointApplyMap.get(serverId);
        if (null == serverAppointApplyMap) {
            return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
        }
        Map<String, MarriageInfo> userAppointApplyMap = serverAppointApplyMap.get(userId);
        if (null == userAppointApplyMap) {
            return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
        }
        MarriageInfo marriageInfo = userAppointApplyMap.get(childUid);
        if (null == marriageInfo) {
            return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
        }
        synchronized (locker) {
            userAppointApplyMap.remove(childUid);
            if (marriageInfo.getStatus() != eMarriageStatusType.CrossPublish) {
                return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
            }
            marriageInfo.setAppointUserId(0);
            marriageInfo.setPartnerServerId(0);
            marriageInfo.setStatus(eMarriageStatusType.WAIT);
        }
        //通知对方被拒绝
        Map<Long, Map<Long, List<String>>> dataMap = new ConcurrentHashMap<>();
        dataMap.put(marriageInfo.getServerId(), new ConcurrentHashMap<>());
        dataMap.get(marriageInfo.getServerId()).put(marriageInfo.getUserId(), new ArrayList<>());
        dataMap.get(marriageInfo.getServerId()).get(marriageInfo.getUserId()).add(marriageInfo.getChildUid());
        notifyRefuseApply(dataMap);
        return 0;
    }

    /**
     * 拒绝所有联姻申请
     *
     * @param groupId
     * @param serverId
     * @param userId
     * @return
     */
    public static int refuseAllMarriage(int groupId, long serverId, long userId) {
        Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointApplyMap = appointApplyMap.get(groupId);
        if (null == groupAppointApplyMap) {
            return 0;
        }
        Map<Long, Map<String, MarriageInfo>> serverAppointApplyMap = groupAppointApplyMap.get(serverId);
        if (null == serverAppointApplyMap) {
            return 0;
        }
        Map<String, MarriageInfo> userAppointApplyMap = serverAppointApplyMap.get(userId);
        if (null == userAppointApplyMap || userAppointApplyMap.size() <= 0) {
            return 0;
        }
        //通知对方被拒绝
        Map<Long, Map<Long, List<String>>> dataMap = new ConcurrentHashMap<>();
        synchronized (locker) {
            for (MarriageInfo marriageInfo : userAppointApplyMap.values()) {
                if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                    marriageInfo.setAppointUserId(0);
                    marriageInfo.setPartnerServerId(0);
                    marriageInfo.setStatus(eMarriageStatusType.WAIT);
                    addReturnConsumeMap(dataMap, marriageInfo);
                }
            }
            //清空
            userAppointApplyMap.clear();
        }
        if (dataMap.size() > 0) {
            notifyRefuseApply(dataMap);
        }
        return 0;
    }

    /**
     * 处理联姻请求
     *
     * @param serverId
     * @param userId
     * @param marriageInfo
     * @param partnerChildUid
     * @return
     */
    public static int agreeMarriage(long serverId, long userId, MarriageInfo marriageInfo, String partnerChildUid) {
        CrossMarriageGroup marriageGroup = CrossMarriageGroupMgr.getCrossMarriageGroupByServerId(serverId);
        if (!CrossMarriageGroupMgr.canCrossMarriage(marriageGroup)) {
            return GameErrorCode.E_CROSS_MARRIAGE_NO_OPEN;
        }
        MarriageInfo partnerMarriage = allMarriageMap.get(partnerChildUid);
        if (null == partnerMarriage) {
            return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
        }
        if (!marriageGroup.getServerList().contains(partnerMarriage.getServerId())) {
            return GameErrorCode.E_CROSS_MARRIAGE_PARTNER_NO_IN_GROUP;
        }
        if (partnerMarriage.getServerId() == serverId) {
            return GameErrorCode.E_CROSS_MARRIAGE_SERVER_NO_SAME;
        }
        if (partnerMarriage.getUserId() == userId) {
            return GameErrorCode.E_MARRIAGE_NO_SELF;
        }
        if (partnerMarriage.getAppointUserId() > 0) {
            if (partnerMarriage.getAppointUserId() != userId || partnerMarriage.getPartnerServerId() != serverId) {
                return GameErrorCode.E_MARRIAGE_APPLY_NO_FOUND;
            }
        }
        //检查双方性别 等等
        if (marriageInfo.getChildSex() == partnerMarriage.getChildSex()) {
            return GameErrorCode.E_MARRIAGE_SEX_WRONG;
        }
        //判断是否过期
        if (isOverApplyTime(partnerMarriage)) {
            return GameErrorCode.E_MARRIAGE_IS_OVER_TIME;
        }
        //判断发布状态
        if (partnerMarriage.getStatus() != eMarriageStatusType.CrossPublish) {
            return GameErrorCode.E_MARRIAGE_STATE_NO_APPLY;
        }
        if (marriageInfo.getChildEarnSpeed().compareTo(partnerMarriage.getLimitEarnSpeed()) < 0) {
            return GameErrorCode.E_CROSS_MARRIAGE_EARNSPEED_LIMIT;
        }

        CrossMarriageProto.CrossMarriageAgreeCrossDealReqMsg.Builder dealMsg = CrossMarriageProto.CrossMarriageAgreeCrossDealReqMsg.newBuilder();
        dealMsg.setApplyData(MarriagePb.parseMarriageApplyTempMsg(marriageInfo));
        dealMsg.setPartnerChildUid(partnerChildUid);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_MARRIAGE_TO_PARTNER_DEAL_AGREE, dealMsg);
        MessageHelper.sendPacket(partnerMarriage.getServerId(), partnerMarriage.getUserId(), pbMsg);
        return 0;
    }

    /**
     * 对方联姻处理完，来最终修改状态
     *
     * @param partnerChildUid
     */
    public static void agreeMarriageFinalDeal(String partnerChildUid) {
        MarriageInfo tempMarriage = allMarriageMap.get(partnerChildUid);
        if(null != tempMarriage) {
            synchronized (locker) {
                if (tempMarriage.getStatus() == eMarriageStatusType.CrossPublish) {
                    tempMarriage.setStatus(eMarriageStatusType.MARRIED);
                }
            }
        }
    }

    /**
     * 获取指向性联姻
     *
     * @param groupId
     * @param serverId
     * @param userId
     * @return
     */
    public static List<MarriageInfo> getAppointApply(int groupId, long serverId, long userId) {
        List<MarriageInfo> dataList = new ArrayList<>();
        Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointMap = appointApplyMap.get(groupId);
        if (null == groupAppointMap) {
            return dataList;
        }
        Map<Long, Map<String, MarriageInfo>> serverAppointMap = groupAppointMap.get(serverId);
        if (null == serverAppointMap) {
            return dataList;
        }
        Map<String, MarriageInfo> userAppointMap = serverAppointMap.get(userId);
        if (null == userAppointMap) {
            return dataList;
        }
        List<MarriageInfo> applyList = new ArrayList<>(userAppointMap.values());
        for (MarriageInfo marriageInfo : applyList) {
            if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                if (!isOverApplyTime(marriageInfo)) {
                    dataList.add(marriageInfo);
                }
            } else {//不是发布状态
                userAppointMap.remove(marriageInfo.getChildUid());
            }
        }
        return dataList;
    }

    /**
     * 通知申请被拒绝
     *
     * @param applyMap
     */
    private static void notifyRefuseApply(Map<Long, Map<Long, List<String>>> applyMap) {
        for (Map.Entry<Long, Map<Long, List<String>>> serverEntry : applyMap.entrySet()) {
            CrossMarriageProto.CrossMarriageRefuseNotifyListMsg.Builder listMsg = MarriagePb.parseCrossMarriageRefuseNotifyListMsg(serverEntry.getValue());
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_MARRIAGE_REFUSE_NOTIFY_SERVER, listMsg);
            MessageHelper.sendPacket(serverEntry.getKey(), 0, pbMsg);
        }
    }

    /**
     * 分组里面是否存在
     *
     * @param groupId
     * @param childUid
     * @return
     */
    private static boolean isServerApplyExist(int groupId, String childUid) {
        Map<String, MarriageInfo> groupMap = serverApplyMap.get(groupId);
        if (null == groupMap) {
            return false;
        }
        return groupMap.containsKey(childUid);
    }

    /**
     * 发布时间是否超时
     */
    private static boolean isOverApplyTime(MarriageInfo marriageInfo) {
        return System.currentTimeMillis() / 1000 - marriageInfo.getPublishTime() > GameConfig.MARRIAGE_PUBLISH_TIME;
    }

    /**
     * 处理超时的联姻
     *
     * @param childUid
     */
    public static void dealMarriageOverTime(String childUid) {
        MarriageInfo marriageInfo = allMarriageMap.get(childUid);
        if (null == marriageInfo) {
            return;
        }
        synchronized (locker) {
            if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                marriageInfo.setAppointUserId(0);
                marriageInfo.setPartnerServerId(0);
                marriageInfo.setStatus(eMarriageStatusType.WAIT);
            }
        }
    }

    /**
     * 分组变更
     */
    private static void groupChange() {
        Map<Long, Map<Long, List<String>>> applyMap = new ConcurrentHashMap<>();
        synchronized (locker) {
            for (Map.Entry<Integer, Map<String, MarriageInfo>> dataEntry : serverApplyMap.entrySet()) {
                for (MarriageInfo marriageInfo : dataEntry.getValue().values()) {
                    if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish && (
                            !CrossMarriageGroupMgr.canCrossMarriage(marriageInfo.getServerId()) ||
                                    CrossMarriageGroupMgr.getGroupIdByServerId(marriageInfo.getServerId()) != dataEntry.getKey()
                    )) {
                        addReturnConsumeMap(applyMap, marriageInfo);
                        marriageInfo.setStatus(eMarriageStatusType.WAIT);
                    }
                }
            }
            for (Map.Entry<Integer, Map<Long, Map<Long, Map<String, MarriageInfo>>>> groupEntry : appointApplyMap.entrySet()) {
                for (Map.Entry<Long, Map<Long, Map<String, MarriageInfo>>> serverEntry : groupEntry.getValue().entrySet()) {
                    if (!CrossMarriageGroupMgr.canCrossMarriage(serverEntry.getKey()) ||
                            groupEntry.getKey() != CrossMarriageGroupMgr.getGroupIdByServerId(serverEntry.getKey())) {//服务器已不在分组了
                        for (Map<String, MarriageInfo> userDataMap : serverEntry.getValue().values()) {
                            for (MarriageInfo marriageInfo : userDataMap.values()) {
                                if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                                    addReturnConsumeMap(applyMap, marriageInfo);
                                    marriageInfo.setStatus(eMarriageStatusType.WAIT);
                                }
                            }
                        }
                    } else {//服务器还在分组
                        for (Map<String, MarriageInfo> userDataMap : serverEntry.getValue().values()) {
                            for (MarriageInfo marriageInfo : userDataMap.values()) {
                                //发布联姻的人不在分组了
                                if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish && (
                                        !CrossMarriageGroupMgr.canCrossMarriage(marriageInfo.getServerId()) ||
                                                CrossMarriageGroupMgr.getGroupIdByServerId(marriageInfo.getServerId()) != groupEntry.getKey()
                                )) {
                                    addReturnConsumeMap(applyMap, marriageInfo);
                                    marriageInfo.setStatus(eMarriageStatusType.WAIT);
                                }
                            }
                        }
                    }
                }
            }
        }
        //到游戏服取消、返还消耗
        notifyRefuseApply(applyMap);
    }

    /**
     * 增加到返还消耗map
     *
     * @param applyMap
     * @param marriageInfo
     */
    private static void addReturnConsumeMap(Map<Long, Map<Long, List<String>>> applyMap, MarriageInfo marriageInfo) {
        if (!applyMap.containsKey(marriageInfo.getServerId())) {
            applyMap.put(marriageInfo.getServerId(), new ConcurrentHashMap<>());
        }
        Map<Long, List<String>> userApplyMap = applyMap.get(marriageInfo.getServerId());
        if (!userApplyMap.containsKey(marriageInfo.getUserId())) {
            userApplyMap.put(marriageInfo.getUserId(), new ArrayList<>());
        }
        List<String> dataList = userApplyMap.get(marriageInfo.getUserId());
        if (!dataList.contains(marriageInfo.getChildUid())) {
            dataList.add(marriageInfo.getChildUid());
        }
    }

    private static void notifyServerReload() {
        int channelId = ConfigHelper.getInt("channelId");
        List<Long> serverList = CrossMarriageGroupMgr.getBeforeChangeServerList(channelId);
        List<CrossMarriageGroup> marriageGroupList = CrossMarriageGroupMgr.getCrossMarriageGroupList(channelId);
        for (CrossMarriageGroup marriageGroup : marriageGroupList) {
            for (long serverId : marriageGroup.getServerList()) {
                if (!serverList.contains(serverId)) {
                    serverList.add(serverId);
                }
            }
        }
        CommonProto.NullValueMsg.Builder msg = CommonProto.NullValueMsg.newBuilder();
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_MARRIAGE_GROUP_RELOAD_NOTIFY, msg);
        for (long serverId : serverList) {
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    /**
    * 描述：黑名单处理指定联姻
    * 作者：zrq
    * 时间：2023/1/3
    * 参数：

    * 返回值：
    **/
    public static void blacklistRemoveAppointMarriage(int groupId, long serverId, long userId, long blacklistUserId, long blacklistServerId) {
        Map<Long, Map<Long, Map<String, MarriageInfo>>> groupAppointApplyMap = appointApplyMap.get(groupId);
        if (null == groupAppointApplyMap) {
            return;
        }
        Map<Long, Map<String, MarriageInfo>> serverAppointApplyMap = groupAppointApplyMap.get(serverId);
        if (null == serverAppointApplyMap) {
            return;
        }
        Map<String, MarriageInfo> userAppointApplyMap = serverAppointApplyMap.get(userId);
        if (null == userAppointApplyMap || userAppointApplyMap.size() <= 0) {
            return;
        }
        //通知对方被拒绝
        Map<Long, Map<Long, List<String>>> dataMap = new ConcurrentHashMap<>();
        List<String> removeList = new ArrayList<>();
        synchronized (locker) {
            for (MarriageInfo marriageInfo : userAppointApplyMap.values()) {
                if(marriageInfo.getUserId() == blacklistUserId && marriageInfo.getServerId() == blacklistServerId) {
                    if (marriageInfo.getStatus() == eMarriageStatusType.CrossPublish) {
                        marriageInfo.setAppointUserId(0);
                        marriageInfo.setPartnerServerId(0);
                        marriageInfo.setStatus(eMarriageStatusType.WAIT);
                        addReturnConsumeMap(dataMap, marriageInfo);
                    }
                    removeList.add(marriageInfo.getChildUid());
                }
            }
            for(String childUid : removeList){
                userAppointApplyMap.remove(childUid);
            }
        }
        if (dataMap.size() > 0) {
            //拒绝通知
            notifyRefuseApply(dataMap);
            //重新同步指定联姻列表
            List<MarriageInfo> marriageInfoList = CrossGroupMarriageMgr.getAppointApply(groupId, serverId, userId);
            MarriageProto.MarriageApplyListMsg.Builder listMsg = MarriagePb.parseMarriageApplyListMsg(marriageInfoList);
            YanQuMessage pbListMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_MARRIAGE_APPOINT_APPLY_LIST, listMsg);
            MessageHelper.sendPacket(serverId, userId, pbListMsg);
        }
    }
}
